package com.scrcu.cloud.wechat.home.endpoint.common.utils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @auther: siliang liu
 * @date: 2024/06/18 8:57
 * @description: 雪花算法id生成
 * @version: 1.0.0
 */
public class SnowWorkId {

    /**
     * 开始时间戳（2023-00-00）
     */
    private static final long startTmp = 1704038400000L;

    /**
     * 序列在id中占的位数
     */
    private final long seqBits = 12L;

    /**
     * 毫秒内序列（0-4095）
     */
    private long sequence = 0L;

    /**
     * 生产序列的掩码（4095）
     */
    private final long seqMask = ~(-1L << seqBits);

    /**
     * 上次生成ID的时间戳
     */
    private long lastTmp = -1L;

    /**
     * 单机版
     */
    private static SnowWorkId snowWorkId;

    public SnowWorkId() {

    }

    public synchronized long nextId() {
        long timestamp = timeGen();
        // 如果当前时间小于上次生成id的时间戳，说明系统时钟回拨
        if (timestamp < lastTmp) {
            throw new RuntimeException(
                    String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTmp - timestamp)
            );
        }
        // 如果是同一时间生成，则进行毫秒内序列
        if (lastTmp == timestamp) {
            sequence = (sequence + 1) & seqMask;
            // 毫秒内序列溢出
            if (sequence == 0) {
                // 阻塞到下一个毫秒
                timestamp = tilNextMillis(lastTmp);
            }
        }
        // 时间戳改变，重置序列
        else {
            sequence = 0;
        }
        // 上次生成id的时间戳
        lastTmp = timestamp;
        // 移位并通过或运算拼到一起组成64位的id
        return ((timestamp - startTmp) << seqBits) | sequence;
    }

    /**
     * 阻塞到下一毫秒
     *
     * @param lastTmp 上次生成id时间戳
     * @return 当前时间戳
     */
    private long tilNextMillis(long lastTmp) {
        long timestamp = timeGen();
        while (timestamp <= lastTmp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    static {
        snowWorkId = new SnowWorkId();
    }

    /**
     * 获取id
     *
     * @return id
     */
    public static long generateId() {
        return snowWorkId.nextId();
    }

    /**
     * 获取时间戳
     *
     * @return tmp
     */
    private long timeGen() {
        return System.currentTimeMillis();
    }


    public static void main(String[] args) {
        long id = new SnowWorkId().nextId();
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDateTime createDate = LocalDateTime.now();
        String struid =  createDate.format(dateFormatter)+StrUtil.padZero(id);  //雪花算法生成id
        System.out.println(struid);
        System.out.println("2024070900000067391379296256".length());
//        long id = new SnowWorkId().nextId();
//        System.out.println(StrUtil.padZero(id));
//        System.out.println(id);
//        67386870284288
//        67387078447104
    }
}
